﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Resources;

namespace Sonce.Editor
{
	public partial class Editor
	{
		#region Dependency properties
		/// <summary>
		/// Gets or sets the current color palette.
		/// </summary>
		public Palette Palette
		{
			get
			{
				Palette result = GetValue(PaletteProperty) as Palette;
				if (result == null)
				{
					result = Palette.Default;
					SetValue(PaletteProperty, result);
				}
				return result;
			}
			set
			{
				SetValue(PaletteProperty, value);
			}
		}

		public static readonly DependencyProperty PaletteProperty = DependencyProperty.Register("Palette", typeof(Palette), typeof(Editor), new PropertyMetadata(PaletteChanged));

		private static void PaletteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
		}
		#endregion

		#region Loading methods
		/// <summary>
		/// Loads a palette from embedded resources.
		/// </summary>
		/// <param name="paletteName">Name of a palette (file name without extension).</param>
		/// <returns>Returns true on success.</returns>
		public bool LoadPalette(string paletteName)
		{
			string path = string.Format("Resources/Palettes/{0}.xaml", paletteName);
			Stream stream = Helper.GetResourceStream(path);
			return LoadPalette(stream);
		}

		/// <summary>
		/// Loads a palette from external source.
		/// </summary>
		/// <param name="paletteUri">Absolute uri to a palette file.</param>
		public void LoadPalette(Uri paletteUri)
		{
			WebClient client = new WebClient();
			client.OpenReadCompleted += (sender, e) =>
			{
				LoadPalette(e.Result);
			};
			client.OpenReadAsync(paletteUri);
		}

		/// <summary>
		/// Loads a palette from xaml stream.
		/// </summary>
		/// <param name="paletteStream">Xaml as stream.</param>
		/// <returns>Returns true on success.</returns>
		public bool LoadPalette(Stream paletteStream)
		{
			bool completed = false;
			if (paletteStream != null && paletteStream.CanRead)
			{
				int read = 0;
				int size = 1024;
				byte[] buffer = new byte[size];
				StringBuilder builder = new StringBuilder();

				//Read whole stream
				while ((read = paletteStream.Read(buffer, 0, size)) > 0)
				{
					builder.Append(Encoding.UTF8.GetString(buffer, 0, read));
				}

				//Create xaml object from string
				object obj = XamlReader.Load(builder.ToString());
				if (obj != null && obj is ResourceDictionary)
				{
					completed = LoadPalette(obj as ResourceDictionary);
				}
			}
			return completed;
		}

		/// <summary>
		/// Loads a palette from the specified ResourceDictionary.
		/// </summary>
		/// <param name="paletteResources"></param>
		/// <returns></returns>
		protected bool LoadPalette(ResourceDictionary paletteResources)
		{
			bool completed = false;
			if (paletteResources != null && paletteResources.Count > 0)
			{
				Palette palette = new Palette();
				//palette.Background = paletteResources["Background"] as Color;
				throw new NotImplementedException("Fill Palette object with resources.");
				this.Palette = palette;
				completed = true;
			}
			return completed;
		}

		/// <summary>
		/// Loads a custom palette.
		/// </summary>
		/// <param name="palette"></param>
		/// <returns></returns>
		protected bool LoadPalette(Palette palette)
		{
			this.Palette = palette;
			return (palette != null);
		}
		#endregion
	}

	public partial class Palette
	{
		#region Properties
		public Brush BackgroundBrush
		{
			get;
			set;
		}

		public Brush GridStrokeBrush
		{
			get;
			set;
		}

		public Brush GridFillBrush
		{
			get;
			set;
		}

		public Brush CursorStrokeBrush
		{
			get;
			set;
		}

		public Brush CursorFillBrush
		{
			get;
			set;
		}

		public Brush NodeStrokeBrush
		{
			get;
			set;
		}

		public Brush NodeFillBrush
		{
			get;
			set;
		}

		public Brush WorkingStrokeBrush
		{
			get;
			set;
		}

		public Brush WorkingFillBrush
		{
			get;
			set;
		}

		public Brush SelectStrokeBrush
		{
			get;
			set;
		}

		public Brush SelectFillBrush
		{
			get;
			set;
		}

		public Brush FloatStrokeBrush
		{
			get;
			set;
		}

		public Brush FloatFillBrush
		{
			get;
			set;
		}

		public Brush PreviewStrokeBrush
		{
			get;
			set;
		}

		public Brush PreviewFillBrush
		{
			get;
			set;
		}

		public Brush HighlightStrokeBrush
		{
			get;
			set;
		}

		public Brush HighlightFillBrush
		{
			get;
			set;
		}
		#endregion

		#region Constructor
		public Palette()
		{
		}
		#endregion

		#region Static properties
		public static Palette Default
		{
			get
			{
				Palette palette = new Palette();

				palette.BackgroundBrush = Helper.GetBrush("#FF2F2F2F");

				palette.CursorStrokeBrush = new SolidColorBrush(Colors.Yellow);
				palette.CursorFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.SelectStrokeBrush = new SolidColorBrush(Colors.Green);
				palette.SelectFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.NodeStrokeBrush = new SolidColorBrush(Colors.Yellow);
				palette.NodeFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.FloatStrokeBrush = new SolidColorBrush(Colors.Green);
				palette.FloatFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.WorkingStrokeBrush = new SolidColorBrush(Colors.White);
				palette.WorkingFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.PreviewStrokeBrush = new SolidColorBrush(Colors.Green);
				palette.PreviewFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.HighlightStrokeBrush = new SolidColorBrush(Colors.Purple);
				palette.HighlightFillBrush = new SolidColorBrush(Colors.Transparent);

				palette.GridStrokeBrush = new SolidColorBrush(Colors.White);
				palette.GridFillBrush = new SolidColorBrush(Colors.Transparent);

				return palette;
			}
		}
		#endregion

		#region Static methods
		public static Palette Create(ResourceDictionary resources)
		{
			Palette palette = new Palette();

			palette.BackgroundBrush = resources["BackgroundBrush"] as Brush;

			palette.CursorStrokeBrush = resources["CursorStrokeBrush"] as Brush;
			palette.CursorFillBrush = resources["CursorFillBrush"] as Brush;

			palette.SelectStrokeBrush = resources["SelectStrokeBrush"] as Brush;
			palette.SelectFillBrush = resources["SelectFillBrush"] as Brush;

			palette.NodeStrokeBrush = resources["NodeStrokeBrush"] as Brush;
			palette.NodeFillBrush = resources["NodeFillBrush"] as Brush;

			palette.FloatStrokeBrush = resources["FloatStrokeBrush"] as Brush;
			palette.FloatFillBrush = resources["FloatFillBrush"] as Brush;

			palette.WorkingStrokeBrush = resources["WorkingStrokeBrush"] as Brush;
			palette.WorkingFillBrush = resources["WorkingFillBrush"] as Brush;

			palette.PreviewStrokeBrush = resources["PreviewStrokeBrush"] as Brush;
			palette.PreviewFillBrush = resources["PreviewFillBrush"] as Brush;

			palette.HighlightStrokeBrush = resources["HighlightStrokeBrush"] as Brush;
			palette.HighlightFillBrush = resources["HighlightFillBrush"] as Brush;

			palette.GridStrokeBrush = resources["GridStrokeBrush"] as Brush;
			palette.GridFillBrush = resources["GridFillBrush"] as Brush;

			return palette;
		}
		#endregion
	}
}
